package httpx

import (
	"bytes"
	"net/http"
	"time"

	kerrors "github.com/go-kratos/kratos/v2/errors"
	khttp "github.com/go-kratos/kratos/v2/transport/http"
)

type Response struct {
	Code      int    `json:"code"`
	Msg       string `json:"msg"`
	Data      any    `json:"data"`
	Timestamp string `json:"timestamp"`
}

func SuccessEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {
	resp := &Response{
		Code:      200,
		Msg:       "success",
		Data:      v,
		Timestamp: time.Now().Format("2006-01-02 15:04:05"),
	}
	if v == nil {
		return nil
	}
	if rd, ok := v.(khttp.Redirector); ok {
		url, code := rd.Redirect()
		http.Redirect(w, r, url, code)
		return nil
	}
	codec, _ := khttp.CodecForRequest(r, "Accept")
	respData, err := codec.Marshal(resp)
	if err != nil {
		return err
	}
	data, err := codec.Marshal(v)
	if err != nil {
		return err
	}

	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	_, err = w.Write(bytes.Replace(respData, []byte("null"), data, 1))
	if err != nil {
		return err
	}
	return nil
}

func ErrorEncoder(w http.ResponseWriter, r *http.Request, err error) {
	if err == nil {
		return
	}
	e := kerrors.FromError(err)
	resp := &Response{
		Code:      int(e.Status.Code),
		Msg:       e.Status.Reason,
		Data:      nil,
		Timestamp: time.Now().Format("2006-01-02 15:04:05"),
	}
	codec, _ := khttp.CodecForRequest(r, "Accept")
	body, err := codec.Marshal(resp)
	w.WriteHeader(http.StatusOK)
	if err != nil {
		return
	}
	w.Header().Set("Content-Type", "application/json")
	_, _ = w.Write(body)
}
